#include <ProcessManager.h>

ProcessManager::~ProcessManager()
{
	ClearAllProcesses();
}

unsigned int ProcessManager::UpdateProcesses(double deltaSecs)
{
	unsigned short int successCount = 0;
	unsigned short int failCount = 0;

	ProcessList::iterator it = m_processList.begin();
	while ( it != m_processList.end())
	{
		StrongProcessPtr pCurrProcess = (*it);

		ProcessList::iterator thisIt = it;
		++it;

		// process is uninitialized, so initialize it
        if (pCurrProcess->GetState() == Process::UNINITIALIZED)
            pCurrProcess->VInit();

		//the OnExpire func of the process has not changed the state
		//so the manager will manually change it to succeeded
		if (pCurrProcess->GetState() == Process::EXPIRED)
			pCurrProcess->SetState(Process::SUCCEEDED);
		else if (pCurrProcess->IsExpired())
			pCurrProcess->SetState(Process::EXPIRED);

        // give the process an update tick if it's running
        if (pCurrProcess->GetState() == Process::RUNNING)
		{
			if (pCurrProcess->IsTimeToUpdate())
			{
				pCurrProcess->VUpdate(pCurrProcess->m_timer.deltaTime());
			}
		}

		if (pCurrProcess->IsDead())
		{
			switch (pCurrProcess->GetState())
			{
				case Process::SUCCEEDED :
                {
                    pCurrProcess->VOnSuccess();
                    StrongProcessPtr pChild = pCurrProcess->RemoveChild();
                    if (pChild)
                        AttachProcess(pChild);
                    else
                        ++successCount;  // only counts if the whole chain completed
                    break;
                }

				case Process::EXPIRED :
				{
					pCurrProcess->VOnExpire();
					break;
				}

                case Process::FAILED :
                {
                    pCurrProcess->VOnFail();
                    ++failCount;
                    break;
                }

                case Process::ABORTED :
                {
                    pCurrProcess->VOnAbort();
                    ++failCount;
                    break;
                }

			}
			if (pCurrProcess->GetState() != Process::EXPIRED)
				m_processList.erase(thisIt);
		}
	}
	return ((successCount << 16) | failCount);
}

WeakProcessPtr ProcessManager::AttachProcess(StrongProcessPtr pProcess)
{
    m_processList.push_back(pProcess);
    return WeakProcessPtr(pProcess);
}

void ProcessManager::ClearAllProcesses(void)
{
    m_processList.clear();
}

void ProcessManager::AbortAllProcesses(bool immediate)
{
    ProcessList::iterator it = m_processList.begin();
    while (it != m_processList.end())
    {
        ProcessList::iterator tempIt = it;
        ++it;

        StrongProcessPtr pProcess = *tempIt;
        if (pProcess->IsAlive())
        {
            pProcess->SetState(Process::ABORTED);
            if (immediate)
            {
                pProcess->VOnAbort();
                m_processList.erase(tempIt);
            }
        }
    }
}